package com.yinghuo.risk.frigate.core.aspect;

import com.yinghuo.risk.frigate.core.anno.HasRole;
import com.yinghuo.risk.frigate.core.enums.Policy;
import com.yinghuo.risk.frigate.core.exception.FrigateException;
import com.yinghuo.risk.frigate.core.exception.NullUserLoginInfoException;
import com.yinghuo.risk.frigate.core.exception.PermissionException;
import com.yinghuo.risk.frigate.core.handler.CacheHandler;
import com.yinghuo.risk.frigate.core.handler.TokenIdHandler;
import com.yinghuo.risk.frigate.core.info.UserLoginInfo;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.util.StringUtils;

import java.util.Collections;
import java.util.List;

/**
 * com.yinghuo.risk.frigate.core.aspect
 *
 * @author 白雨浓
 * date: 2018/10/19 11:11
 * content: 角色 Controller切点
 */
@Aspect
@Order(0)
public class RoleAspect {

    private final CacheHandler<? extends UserLoginInfo> cacheHandler;

    private final TokenIdHandler tokenIdHandler;

    public RoleAspect(CacheHandler<? extends UserLoginInfo> cacheHandler, TokenIdHandler tokenIdHandler) {
        this.cacheHandler = cacheHandler;
        this.tokenIdHandler = tokenIdHandler;
    }

    @Before("execution(public * *(..)) && @annotation(hasRole)")
    public void before(HasRole hasRole) {

        String tokenId = tokenIdHandler.getTokenId();

        if (StringUtils.isEmpty(tokenId)) {
            throw new PermissionException("Permission denied");
        }

        UserLoginInfo info = cacheHandler.find(tokenId);

        if (info == null) {
            throw new NullUserLoginInfoException("Not found UserLoginInfo in cache." +
                    " Please use UserLoginEvent login input UserLoginInfo for cache");
        }

        if (Policy.AND.equals(hasRole.policy())) {
            int sum = 0;

            for (String role : hasRole.value()) {

                boolean has = info.roleSet().contains(role);
                sum += has ? 1 : 0;
            }

            if (sum != hasRole.value().length) {
                throw new PermissionException("Permission denied");
            }
        } else if (Policy.OR.equals(hasRole.policy())) {
            boolean pass = false;

            for (String role : hasRole.value()) {

                boolean has = info.roleSet().contains(role);
                if (has) {
                    pass = true;
                    break;
                }
            }

            if (!pass) {
                throw new PermissionException("Permission denied");
            }
        } else {
            throw new FrigateException("Policy not null");
        }
    }
}
